using System;
using System.Collections.Generic;
using System.Linq;
using Tycho.Parser.Peg;

namespace Tycho.Grammar {
    public class SequenceRuleCompiler : IRuleCompiler {
        private readonly IRuleCompiler RuleCompiler;
        private readonly Func<ISequenceRuleInfixInformationBuilder> CreateInfixInformationBuilder;

        public SequenceRuleCompiler (IRuleCompiler ruleCompiler) : this (ruleCompiler, () => new SequenceRuleInfixInformationBuilder ()) {}

        public SequenceRuleCompiler (IRuleCompiler ruleCompiler, Func<ISequenceRuleInfixInformationBuilder> createInfixInformationBuilder) {
            RuleCompiler = ruleCompiler;
            CreateInfixInformationBuilder = createInfixInformationBuilder;
        }

        public IRule Compile (ITerm term, ProductionCompilerContext context, ICaptureCounter captureCounter) {
            ISequenceRuleInfixInformationBuilder infixInformationBuilder = CreateInfixInformationBuilder ();
            var compositeTerm = (CompositeTerm) term;
            IEnumerable<ITerm> terms = ((ListTerm) compositeTerm.SubTerms ["rules"]).Terms;

            var rules = new IRule[terms.Count ()];

            int n = 0;
            IRule lastRule = null;
            foreach (var ruleTerm in terms) {
                IRule rule = RuleCompiler.Compile (ruleTerm, context, captureCounter);

                infixInformationBuilder.Add (rule);

                if (lastRule != null && lastRule.HasProduction && rule is KeywordRule) {
                    var keywordRule = (KeywordRule) rule;

                    lastRule.Production = new RecoveryProduction (lastRule.Production, keywordRule.Production);
                }

                rules[n] = lastRule = rule;

                n++;
            }

            var sequenceRule = new SequenceRule (rules);
            sequenceRule.SetInfixInformation (infixInformationBuilder.CreateInfixInformation ());
            return sequenceRule;
        }
    }
}